/******************************************************************************
* File Name          : l3gd20.h
* Author             : 
* Author             : 
* Version            : 1.0
* Date               : 5/11/2013
* Description        : Descriptor Header for l3gd20d driver file
*
* HISTORY:
* Date        | Modification                                | Author

*******************************************************************************/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __L3GD20
#define __L3GD20

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_i2c.h"
/* Exported types ------------------------------------------------------------*/

//these could change accordingly with the architecture

#ifndef __ARCHDEP__TYPES
#define __ARCHDEP__TYPES
typedef unsigned char u8_t;
typedef unsigned short int u16_t;
typedef short int i16_t;
typedef int i32_t;
typedef signed char i8_t;
typedef float float32_t;
#endif /*__ARCHDEP__TYPES*/

typedef u8_t L3GD20_Int1PinConf_t;
typedef u8_t L3GD20_Int2PinConf_t;
typedef u8_t L3GD20_Int1Conf_t;
typedef u8_t L3GD20_Axis_t;
typedef u8_t L3GD20_WHO_AM_I;

/* Exported common structure --------------------------------------------------------*/

#ifndef __SHARED__TYPES
#define __SHARED__TYPES

typedef enum {
  MEMS_SUCCESS				=		0x01,
  MEMS_ERROR				=		0x00	
} status_t;

typedef enum {
  MEMS_ENABLE				=		0x01,
  MEMS_DISABLE				=		0x00	
} State_t;

typedef struct {
  float32_t AXIS_X;
  float32_t AXIS_Y;
  float32_t AXIS_Z;
} AxesRaw_t;

#endif /*__SHARED__TYPES*/

typedef enum {  
  L3GD20_ODR_95Hz_BW_12_5              =		0x00,
  L3GD20_ODR_95Hz_BW_25				   =		0x01,
  L3GD20_ODR_190Hz_BW_12_5             =		0x04,
  L3GD20_ODR_190Hz_BW_25			   =		0x05,
  L3GD20_ODR_190Hz_BW_50			   =		0x06,
  L3GD20_ODR_190Hz_BW_70			   =		0x07,
  L3GD20_ODR_380Hz_BW_20		       =		0x08,
  L3GD20_ODR_380Hz_BW_25			   =		0x09,
  L3GD20_ODR_380Hz_BW_50			   =		0x0A,
  L3GD20_ODR_380Hz_BW_100              =		0x0B,
  L3GD20_ODR_760Hz_BW_30			   =		0x0C,
  L3GD20_ODR_760Hz_BW_35			   =		0x0D,
  L3GD20_ODR_760Hz_BW_50			   =		0x0E,
  L3GD20_ODR_760Hz_BW_100              =		0x0F
} L3GD20_ODR_t;

typedef enum {
  L3GD20_POWER_DOWN                    =		0x00,
  L3GD20_SLEEP 		                   =		0x01,
  L3GD20_NORMAL			               =		0x02
} L3GD20_Mode_t;

typedef enum {
  L3GD20_HPM_NORMAL_MODE_RES           =               0x00,
  L3GD20_HPM_REF_SIGNAL                =               0x01,
  L3GD20_HPM_NORMAL_MODE               =               0x02,
  L3GD20_HPM_AUTORESET_INT             =               0x03
} L3GD20_HPFMode_t;

typedef enum {
  L3GD20_HPFCF_0                       =               0x00,
  L3GD20_HPFCF_1                       =               0x01,
  L3GD20_HPFCF_2                       = 	           0x02,
  L3GD20_HPFCF_3                       =               0x03,
  L3GD20_HPFCF_4                       =               0x04,
  L3GD20_HPFCF_5                       =               0x05,
  L3GD20_HPFCF_6                       =               0x06,
  L3GD20_HPFCF_7                       =               0x07,
  L3GD20_HPFCF_8                       =               0x08,
  L3GD20_HPFCF_9                       =               0x09
} L3GD20_HPFCutOffFreq_t;

typedef enum {
  L3GD20_PUSH_PULL                     =		0x00,
  L3GD20_OPEN_DRAIN                    =                0x01  
} L3GD20_IntPinMode_t;

typedef enum {
  L3GD20_FULLSCALE_250                 =               0x00,
  L3GD20_FULLSCALE_500                 =               0x01,
  L3GD20_FULLSCALE_2000                =               0x02	
} L3GD20_Fullscale_t;

typedef enum {
  L3GD20_BLE_LSB			 =		0x00,
  L3GD20_BLE_MSB			 =		0x01
} L3GD20_Endianess_t;

typedef enum {
  L3GD20_SPI_4_WIRE                    =               0x00,
  L3GD20_SPI_3_WIRE                    =               0x01
} L3GD20_SPIMode_t;

typedef enum {
  L3GD20_FIFO_DISABLE                  =               0x05,
  L3GD20_FIFO_BYPASS_MODE              =               0x00,
  L3GD20_FIFO_MODE                     =               0x01,
  L3GD20_FIFO_STREAM_MODE              =               0x02,
  L3GD20_FIFO_STREAM_TO_FIFO_MODE      =               0x03,
  L3GD20_FIFO_BYPASS_TO_STREAM_MODE    =               0x04    
} L3GD20_FifoMode_t;

typedef enum {
  L3GD20_NONE                          =               0x00,
  L3GD20_HPF                           =               0x01,
  L3GD20_LPF2                          =               0x02,
  L3GD20_HPFLPF2                       =               0x03
} L3GD20_HPF_LPF2_Enable;

typedef enum {
  L3GD20_THS_X                         =                0x00,
  L3GD20_THS_Y                         =                0x01,  
  L3GD20_THS_Z                         =                0x02
} L3GD20_IntThsAxis;

/* Exported macro ------------------------------------------------------------*/

#ifndef __SHARED__MACROS

#define __SHARED__MACROS
#define ValBit(VAR,Place)         (VAR & (1<<Place))
#define BIT(x) ( (x) )

#endif /*__SHARED__MACROS*/

/* Exported constants --------------------------------------------------------*/

#ifndef __SHARED__CONSTANTS
#define __SHARED__CONSTANTS

#define MEMS_SET                        0x01
#define MEMS_RESET                      0x00

#endif /*__SHARED__CONSTANTS*/


/* The address of the device is normally given as a 7-bit address by the
 * manufacturer. in the case of the STMicro L3GD20 Gyroscope, the manufacturer
 * lists the address as 110101xb. the x-bit is set by tying the SDO pin either
 * high or low. If the SDO pin is tied high, the address becomes 1101011b (0x6B),
 * if tied low it becomes 1101010b (0x6A). 
 * As you know with I2C, to achieve a full 8-bit address and expedite
 * functionality, the 7-bit address is shifted left by one and the new LSB is then
 * used to tell the slave whether the master is writing (LSB = 0) or reading 
 * (LSB = 1) from the slave. 
 * In this driver, the functions are written such the the slave device address
 * shall be defined as SLAVE_ADDRESS << 1.
 *
 * I.E.  L3GD20 Slave address(SDO tied high) = 1101011b = 0x6C  therefore,
 *       #define L3GD20_MEMS_I2C_ADDRESS = 1101011 << 1 = 11010110b = 0xD6
 *
 * I.E.  L3GD20 Slave address(SDO tied low) = 1101010b = 0x6B  therefore,
 *       #define L3GD20_MEMS_I2C_ADDRESS = 1101010 << 1 = 11010100b = 0xD4
 *
 * There is no need to worry about the new LSB/RW bit. The read and write
 * functions in the 'device'.c file will set that bit appropriately.
 */
#define L3GD20_MEMS_I2C_ADDRESS         0xD6

#define L3GD20_ZERO_RATE_250            0x0B
#define L3GD20_ZERO_RATE_500            0x0F
#define L3GD20_ZERO_RATE_2000           0x4B
#define L3GD20_SENSITIVITY_250       0.00875
#define L3GD20_SENSITIVITY_500       0.01750
#define L3GD20_SENSITIVITY_2000       0.7000
/**************CONTROL REGISTERS*****************/
/**************WHO AM I*************/
#define L3GD20_WHO_AM_I  				0x0F

/***************CTRL1***************/
#define L3GD20_CTRL_REG1				0x20
#define L3GD20_ODR_BIT                  BIT(4)
#define L3GD20_PD					    BIT(3)
#define L3GD20_ZEN					    BIT(2)
#define L3GD20_XEN					    BIT(1)
#define L3GD20_YEN					    BIT(0)
#define L3GD20_Z_ENABLE                 0x04
#define L3GD20_X_ENABLE                 0x02
#define L3GD20_Y_ENABLE                 0x01
#define L3GD20_Z_DISABLE                0x00
#define L3GD20_X_DISABLE                0x00
#define L3GD20_Y_DISABLE                0x00

/***************CTRL2***************/
#define L3GD20_CTRL_REG2				0x21
#define L3GD20_HPM					    BIT(4)
#define L3GD20_HPFC3					BIT(3)
#define L3GD20_HPFC2					BIT(2)
#define L3GD20_HPFC1					BIT(1)
#define L3GD20_HPFC0					BIT(0)

/***************CTRL3***************/
#define L3GD20_CTRL_REG3				0x22
#define L3GD20_I1_INT					BIT(7)
#define L3GD20_I1_BOOT				    BIT(6)
#define L3GD20_H_LACTIVE				BIT(5)
#define L3GD20_PP_OD					BIT(4)
#define L3GD20_I2_DRDY				    BIT(3)
#define L3GD20_I2_WTM					BIT(2)
#define L3GD20_I2_ORUN				    BIT(1)
#define L3GD20_I2_EMPTY				    BIT(0)
#define L3GD20_I1_ON_PIN_INT1_ENABLE    0x80
#define L3GD20_I1_ON_PIN_INT1_DISABLE   0x00
#define L3GD20_I1_BOOT_ON_INT1_ENABLE   0x40
#define L3GD20_I1_BOOT_ON_INT1_DISABLE  0x00
#define L3GD20_INT1_ACTIVE_HIGH         0x00
#define L3GD20_INT1_ACTIVE_LOW          0x20
#define L3GD20_I2_DRDY_ON_INT2_ENABLE   0x08
#define L3GD20_I2_DRDY_ON_INT2_DISABLE  0x00
#define L3GD20_WTM_ON_INT2_ENABLE       0x04
#define L3GD20_WTM_ON_INT2_DISABLE      0x00
#define L3GD20_OVERRUN_ON_INT2_ENABLE   0x02
#define L3GD20_OVERRUN_ON_INT2_DISABLE  0x00
#define L3GD20_EMPTY_ON_INT2_ENABLE     0x01
#define L3GD20_EMPTY_ON_INT2_DISABLE    0x00

/***************CTRL4***************/
#define L3GD20_CTRL_REG4				0x23
#define L3GD20_BDU					    BIT(7)
#define L3GD20_BLE					    BIT(6)
#define L3GD20_FS					    BIT(4)
#define L3GD20_SIM					    BIT(0)

/***************CTRL5***************/
#define L3GD20_CTRL_REG5			    0x24
#define L3GD20_BOOT                     BIT(7)
#define L3GD20_FIFO_EN                  BIT(6)
#define L3GD20_HPEN                     BIT(4)
#define L3GD20_INT1_SEL1                BIT(3)
#define L3GD20_INT1_SEL0                BIT(2)
#define L3GD20_OUT_SEL1                 BIT(1)
#define L3GD20_OUT_SEL0                 BIT(0)

/**************GYROSCOPE INTERRUPT REGISTERS***************/
#define L3GD20_INT1_CFG				    0x30
#define L3GD20_INT1_SRC				    0x31
#define L3GD20_INT1_THS_XH				0x32
#define L3GD20_INT1_THS_XL				0x33
#define L3GD20_INT1_THS_YH				0x34
#define L3GD20_INT1_THS_YL				0x35
#define L3GD20_INT1_THS_ZH				0x36
#define L3GD20_INT1_THS_ZL				0x37
#define L3GD20_INT1_DURATION			0x38
#define L3GD20_ANDOR                                   BIT(7)
#define L3GD20_LIR                                     BIT(6)
#define L3GD20_ZHIE                                    BIT(5)
#define L3GD20_ZLIE                                    BIT(4)
#define L3GD20_YHIE                                    BIT(3)
#define L3GD20_YLIE                                    BIT(2)
#define L3GD20_XHIE                                    BIT(1)
#define L3GD20_XLIE                                    BIT(0)
#define L3GD20_INT1_AND                                0x80
#define L3GD20_INT1_OR                                 0x00
#define L3GD20_INT1_LIR_ENABLE                         0x40
#define L3GD20_INT1_LIR_DISABLE                        0x00
#define L3GD20_INT1_ZHIE_ENABLE                        0x20
#define L3GD20_INT1_ZHIE_DISABLE                       0x00
#define L3GD20_INT1_ZLIE_ENABLE                        0x10
#define L3GD20_INT1_ZLIE_DISABLE                       0x00
#define L3GD20_INT1_YHIE_ENABLE                        0x08
#define L3GD20_INT1_YHIE_DISABLE                       0x00
#define L3GD20_INT1_YLIE_ENABLE                        0x04
#define L3GD20_INT1_YLIE_DISABLE                       0x00
#define L3GD20_INT1_XHIE_ENABLE                        0x02
#define L3GD20_INT1_XHIE_DISABLE                       0x00
#define L3GD20_INT1_XLIE_ENABLE                        0x01
#define L3GD20_INT1_XLIE_DISABLE                       0x00

/**********GYROSCOPE: STATUS AND OUTPUT REGISTERS***********/
//OUTPUT REGISTER
#define L3GD20_OUT_X_L					0x28
#define L3GD20_OUT_X_H					0x29
#define L3GD20_OUT_Y_L					0x2A
#define L3GD20_OUT_Y_H					0x2B
#define L3GD20_OUT_Z_L					0x2C
#define L3GD20_OUT_Z_H					0x2D
#define L3GD20_STATUS_REG                   0x27
#define L3GD20_STATUS_REG_ZYXOR             0x07    // 1	:	new data set has over written the previous one
							// 0	:	no overrun has occurred (default)	
#define L3GD20_STATUS_REG_ZOR               0x06    // 0	:	no overrun has occurred (default)
							// 1	:	new Z-axis data has over written the previous one
#define L3GD20_STATUS_REG_YOR               0x05    // 0	:	no overrun has occurred (default)
							// 1	:	new Y-axis data has over written the previous one
#define L3GD20_STATUS_REG_XOR               0x04    // 0	:	no overrun has occurred (default)
							// 1	:	new X-axis data has over written the previous one
#define L3GD20_STATUS_REG_ZYXDA             0x03    // 0	:	a new set of data is not yet available one
                                                        // 1	:	a new set of data is available 
#define L3GD20_STATUS_REG_ZDA               0x02    // 0	:	a new data for the Z-Axis is not available one
                                                        // 1	:	a new data for the Z-Axis is available
#define L3GD20_STATUS_REG_YDA               0x01    // 0	:	a new data for the Y-Axis is not available
                                                        // 1	:	a new data for the Y-Axis is available
#define L3GD20_STATUS_REG_XDA               0x00    // 0	:	a new data for the X-Axis is not available

#define L3GD20_DATAREADY_BIT                L3GD20_STATUS_REG_ZYXDA

#define L3GD20_I_AM_L3GD20			        0xD4

/*************GYROSCOPE FIFO CONTROL REGISTER**************/
#define L3GD20_FM0                          BIT(5)
#define L3GD20_WTM4                         BIT(4)
#define L3GD20_WTM3                         BIT(3)
#define L3GD20_WTM2                         BIT(2)
#define L3GD20_WTM1                         BIT(1)
#define L3GD20_WTM0                         BIT(0)
#define L3GD20_FIFO_CTRL_REG                0x2E
#define L3GD20_FIFO_SRC_REG			        0x2F

/* Exported functions --------------------------------------------------------*/
/**********Sensor Configuration Functions***********/
status_t L3GD20_Init();
status_t L3GD20_SetODR(L3GD20_ODR_t ov);
status_t L3GD20_SetMode(L3GD20_Mode_t md);
status_t L3GD20_SetAxis(L3GD20_Axis_t axis);
status_t L3GD20_SetFullScale(L3GD20_Fullscale_t fs);
status_t L3GD20_SetBDU(State_t bdu);
status_t L3GD20_SetBLE(L3GD20_Endianess_t ble);
status_t L3GD20_SetSPIInterface(L3GD20_SPIMode_t spi);
status_t L3GD20_SetOffset(u8_t Reg);

/***************Filtering Functions****************/
status_t L3GD20_SetHPFMode(L3GD20_HPFMode_t hpf);
status_t L3GD20_SetHPFCutOFF(L3GD20_HPFCutOffFreq_t hpf);status_t L3GD20_HPFEnable(State_t hpf);
status_t L3GD20_SetOutputDataAndFifoFilters(L3GD20_HPF_LPF2_Enable hpf);
status_t L3GD20_SetInt1Filters(L3GD20_HPF_LPF2_Enable hpf);

/***************Interrupt Functions****************/
status_t L3GD20_SetIntPinMode(L3GD20_IntPinMode_t pm);
status_t L3GD20_SetInt1Pin(L3GD20_Int1PinConf_t pinConf);
status_t L3GD20_SetInt2Pin(L3GD20_Int2PinConf_t pinConf);
status_t L3GD20_Int1LatchEnable(State_t latch);
status_t L3GD20_ResetInt1Latch(void);
status_t L3GD20_SetIntConfiguration(L3GD20_Int1Conf_t ic);
status_t L3GD20_SetInt1Threshold(L3GD20_IntThsAxis axis, u16_t ths);
status_t L3GD20_SetInt1Duration(L3GD20_Int1Conf_t id);

/*****************FIFO Functions******************/
status_t L3GD20_FIFOModeEnable(L3GD20_FifoMode_t fm);
status_t L3GD20_SetWaterMark(u8_t wtm);

/****************Reading Functions*****************/
status_t L3GD20_GetSatusReg(u8_t* buff);
status_t L3GD20_GetAngRateRaw(AxesRaw_t* buff);
status_t L3GD20_GetAngRateDeg(AxesRaw_t* buff);
status_t L3GD20_GetAngRateRad(AxesRaw_t* buff);
status_t L3GD20_GetFifoSourceReg(u8_t* buff);
status_t L3GD20_GetInt1Src(u8_t* buff);

/*********************Generic*********************/
u8_t L3GD20_ReadReg(u8_t Reg, u8_t* Data);
u8_t L3GD20_ReadBuffer(u8_t ReadAddr, AxesRaw_t* buff);
u8_t L3GD20_WriteReg(u8_t WriteAddr, u8_t Data);
#endif /* __L3GD20_H */

/***************************************************************END OF FILE****/
